package com.yangfan.thread.thread_wangwenjun07;

/**
 * 读写锁的实现
 */
public class ReadWriteLock {

    //当前正在读的线程的个数
    private int readingReaders = 0;
    //等待读的线程的个数
    private int waitingReaders = 0;

    //正在写的线程的个数 只能有一个 线程在写  读写互斥  写写互斥
    private int writingWriters = 0;
    //正在等待写的线程的个数
    private int waitingWriters = 0;

    //这个参数 能够增加 写锁的 获取锁的机会
    private boolean preferWriter = true;


    public ReadWriteLock() {
        this(true);
    }


    public ReadWriteLock(boolean preferWriter) {
        this.preferWriter = preferWriter;
    }


    /**
     * 读加锁
     * @throws InterruptedException
     */
    public synchronized void readLock() throws InterruptedException {
        this.waitingReaders++;//等待读取的线程 +1 因为现在还没有 开始读 所以是等待
        try {

            //如果现在 正在写的 线程 大于 0  或者  等待写的线程 >0  则进行等待 (preferWriter 为 true 则 代表 写锁优先级高)
            while (writingWriters > 0 || (preferWriter && waitingWriters > 0)) {
                this.wait();
            }

            this.readingReaders++;//正在读取的线程数+1
        } finally {
            this.waitingReaders--; //读完了 等待读的 所以减1
        }
    }

    /**
     * 读解锁
     */
    public synchronized void readUnlock() {
        this.readingReaders--;
        this.notifyAll();
    }



    public synchronized void writeLock() throws InterruptedException {
        this.waitingWriters++;
        try {
            while (readingReaders > 0 || writingWriters > 0) {
                this.wait();
            }
            this.writingWriters++;
        } finally {
            this.waitingWriters--;
        }
    }

    public synchronized void writeUnlock() {
        this.writingWriters--;
        this.notifyAll();
    }

}